// Cell names have been changed in this file by netl_namemap on Mon Jan  3 04:00:15 UTC 2022
////////////////////////////////////////////////////////////////////////////// 
//
//  pcs_raw_rx_ctl.v
//
//  RX control
//
//  Original Author: Ameer Youssef 
//  Current Owner: Gaurav Dubey   
//
////////////////////////////////////////////////////////////////////////////// 
//
// Copyright (C) 2013 Synopsys, Inc.  All rights reserved.
//
// SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of
// Synopsys, Inc., and is fully protected under copyright and trade secret
// laws.  You may not view, use, disclose, copy, or distribute this file or
// any information contained herein except pursuant to a valid written
// license agreement. It may not be used, reproduced, or disclosed to others
// except in accordance with the terms and conditions of that agreement.
//
////////////////////////////////////////////////////////////////////////////// 
//
//    Perforce Information
//    $Author: gdube $
//    $File: //dwh/up16/main/dev/pcs_raw/dig/rtl/pcs_raw_rx_ctl.v $
//    $DateTime: 2019/09/28 22:05:13 $
//    $Revision: #58 $
//
////////////////////////////////////////////////////////////////////////////// 

`include "dwc_e12mp_phy_x4_ns_pcs_raw_macros.v"
`include "dwc_e12mp_phy_x4_ns_jtag_id_code.v"

`timescale 1ns/10fs
module dwc_e12mp_phy_x4_ns_pcs_raw_rx_ctl (
// Clocks and resets
input  wire          cr_clk,
input  wire          cr_rst,
input  wire [2:0]    ref_range,

// PCS RX interface
input  wire          rx_reset_i,
input  wire          rx_req_i,
input  wire [1:0]    rx_rate_i,
input  wire [1:0]    rx_width_i,
input  wire [1:0]    rx_pstate_i,
input  wire          rx_lpd_i,
input  wire [5:0]    rx_ref_ld_val_i,
input  wire [12:0]   rx_vco_ld_val_i,
input  wire          rx_cdr_vco_lowfreq_i,
input  wire          rx_adapt_afe_en_i,
input  wire          rx_adapt_dfe_en_i,
input  wire [2:0]    rx_eq_att_lvl_i,
input  wire [3:0]    rx_eq_vga1_gain_i,
input  wire [3:0]    rx_eq_vga2_gain_i,
input  wire [2:0]    rx_eq_ctle_pole_i,
input  wire [4:0]    rx_eq_ctle_boost_i,
input  wire [7:0]    rx_eq_dfe_tap1_i,
input  wire          rx_disable_i,
input  wire          rx_data_en_i,
input  wire          rx_cdr_track_en_i,
input  wire          rx_offcan_cont_i,
input  wire          rx_adapt_cont_i,
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
input  wire [4:0]    rx_cdr_ppm_max_i,
`endif
output wire          rx_ack_i,
output wire          rx_los_i,
output wire          rx_valid_i,
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
output wire [5:0]    rx_ppm_drift_i,
output wire          rx_ppm_drift_vld_i,
`endif

// Initial power-up done status (from aon_lane register)
input wire           lane_init_pwrup_done_r,
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
input wire [11:0]    rx_cdr_recovery_time_r,
input wire           rx_cdr_detector_en_r,
input wire           rx_cdr_ppm_monitor_mode_r,
input wire           rx_cdr_detector_dis_in_adapt_r,
input wire           rx_adapt_req_sync,
`endif

// RX Adaptation Status and Values (from aon_lane)
input  wire [7:0]    rx_att_adpt_val_r,
input  wire [9:0]    rx_vga_adpt_val_r,
input  wire [2:0]    rx_ctle_pole_adpt_val_r,
input  wire [9:0]    rx_ctle_boost_adpt_val_r,
input  wire [12:0]   rx_dfe_tap1_adpt_val_r,
input  wire [11:0]   rx_dfe_tap2_adpt_val_r,
input  wire [11:0]   rx_dfe_tap3_adpt_val_r,
input  wire [11:0]   rx_dfe_tap4_adpt_val_r,
input  wire [11:0]   rx_dfe_tap5_adpt_val_r,
input  wire          rx_adpt_done_r,

// Fast flags (from aon_lane)
`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
input  wire          rx_fast_vco_cal_r,
`endif
input  wire          rx_fast_pwrup_r,

// PMA RX interface
output wire          rx_pma_reset_i,
output wire          rx_pma_req_i,
output wire [1:0]    rx_pma_rate_i,
output wire [1:0]    rx_pma_width_i,
output wire [1:0]    rx_pma_pstate_i,
output wire          rx_pma_lpd_i,
output wire [5:0]    rx_pma_ref_ld_val_i,
output wire [12:0]   rx_pma_vco_ld_val_i,
output wire          rx_pma_cdr_vco_lowfreq_i,
output wire          rx_pma_adapt_afe_en_i,
output wire          rx_pma_adapt_dfe_en_i,
output wire [2:0]    rx_pma_eq_att_lvl_i,
output wire [3:0]    rx_pma_eq_vga1_gain_i,
output wire [3:0]    rx_pma_eq_vga2_gain_i,
output wire [2:0]    rx_pma_eq_ctle_pole_i,
output wire [4:0]    rx_pma_eq_ctle_boost_i,
output wire [7:0]    rx_pma_eq_dfe_tap1_i,
output wire [6:0]    rx_pma_eq_dfe_tap2_i,
output wire [6:0]    rx_pma_eq_dfe_tap3_i,
output wire [6:0]    rx_pma_eq_dfe_tap4_i,
output wire [6:0]    rx_pma_eq_dfe_tap5_i,
output wire          rx_pma_data_en_i,
output wire          rx_pma_cdr_track_en_i,
input  wire          rx_pma_ack_i,
input  wire          rx_pma_los_i,
input  wire          rx_pma_valid_i,

`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
// PMA RX clock
input  wire          rx_clk_i,
`else
  `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
// PMA RX clock
input  wire          rx_clk_i,
  `endif
`endif

// CREG interface (accessing CREGs in this block)                     
output wire [15:0]   cr_rd_data,
input  wire [15:0]   cr_wr_data,
input  wire          cr_wr_en,
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
input  wire  [6:0]   cr_sel,
`else
input  wire  [4:0]   cr_sel,
`endif

input  wire          scan_mode_i,
input  wire          scan_set_rst_i
);

// -------------------------
// Registers and nets
// -------------------------

wire        cr_rx_rst;
wire        rx_req_crclk;
wire        rx_pma_ack_crclk;
wire        new_req;
wire [1:0]  req_rx_rate_nxt;
wire [1:0]  req_rx_width_nxt;
wire [1:0]  req_rx_pstate_nxt;
wire        req_rx_lpd_nxt;
wire [5:0]  req_rx_ref_ld_val_nxt;
wire [12:0] req_rx_vco_ld_val_nxt;
wire        req_rx_cdr_vco_lowfreq_nxt;
wire        req_rx_adapt_afe_en_nxt;
wire        req_rx_adapt_dfe_en_nxt;
wire        req_rx_vco_freq_change;
wire        req_rate_change;
reg  [1:0]  req_rx_rate;
reg  [1:0]  req_rx_width;
reg  [5:0]  req_rx_ref_ld_val;
reg  [12:0] req_rx_vco_ld_val;
reg         req_rx_cdr_vco_lowfreq;
reg         req_rx_adapt_afe_en;
reg         req_rx_adapt_dfe_en;
reg  [1:0]  req_rx_pstate;
reg         req_rx_lpd;
reg  [2:0]  rx_ctl_state;
reg         rx_ctl_reset;
reg  [1:0]  curr_rx_rate;
reg  [1:0]  curr_rx_width;
reg  [1:0]  curr_rx_pstate;
reg         curr_rx_lpd;
reg  [5:0]  curr_rx_ref_ld_val;
reg  [12:0] curr_rx_vco_ld_val;
reg         curr_rx_cdr_vco_lowfreq;
reg         curr_rx_adapt_afe_en;
reg         curr_rx_adapt_dfe_en;
reg         rx_pma_req_int;
reg  [1:0]  rx_pma_rate_int;
reg  [1:0]  rx_pma_width_int;
reg  [1:0]  rx_pma_pstate_int;
reg         rx_pma_lpd_int;
reg  [5:0]  rx_pma_ref_ld_val_int;
reg  [12:0] rx_pma_vco_ld_val_int;
reg         rx_pma_cdr_vco_lowfreq_int;
reg         rx_pma_adapt_afe_en_int;
reg         rx_pma_adapt_dfe_en_int;
reg         rx_ack_int;
`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
reg         rx_data_en_ovrd;
reg         rx_data_en_ovrd_val;
reg         rx_valid_ovrd;
reg  [12:0] rx_wait_cnt;
wire        rx_wait_cnt_ne_0;
wire [12:0] rx_wait_cnt_dec;
`endif

wire        rate_chg_in_p1_r;
wire        en_rx_ctl_fsm_r;
wire  [8:0] los_mask_cnt_r;
wire  [4:0] rx_data_en_ovrd_cnt_r;
wire [10:0] int_ref_trck_cnt_r;
`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
reg   [6:0] rx_data_en_ovrd_cr_cyc;
reg  [12:0] int_ref_trck_cr_cyc;
`endif
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
wire           rx_cdr_data_en;
`endif

// Add RX Reset
// Mantis 7223 Remove ATPG coverage flop for cascaded pcs_raw_gen_rst_sync
dwc_e12mp_phy_x4_ns_pcs_raw_gen_rst_sync #(.ATPG_COV(0)) cr_rx_rst_sync (
  .sync_rst        (cr_rx_rst),
  .clk             (cr_clk),
  .scan_mode_i     (scan_mode_i),
  .scan_set_rst_i  (scan_set_rst_i),
  .async_rst       (cr_rst | rx_reset_i)
);

// Set PMA tx reset
assign rx_pma_reset_i = cr_rx_rst;

// Synchronize PCS RX request to cr_clk domain
dwc_e12mp_phy_x4_ns_gen_sync rx_req_sync (
  .q   (rx_req_crclk),
  .clk (cr_clk),
  .rst (cr_rx_rst),
  .d   (rx_req_i)
);

// Synchronize PMA RX ack to cr_clk domain
// (needs to be asserted from the beginning)
dwc_e12mp_phy_x4_ns_gen_sync #(.RST_VAL(1)) rx_pma_ack_sync (
  .q   (rx_pma_ack_crclk),
  .clk (cr_clk),
  .rst (cr_rx_rst),
  .d   (rx_pma_ack_i)
);

// if received a request, or out of reset and pma ack has deasserted
// and FSM is not by-passed
assign new_req = rx_req_crclk | (rx_ctl_reset & ~rx_pma_ack_crclk) && en_rx_ctl_fsm_r;

// RX VCO freq change request
assign req_rx_vco_freq_change = (req_rx_ref_ld_val != curr_rx_ref_ld_val) |
                                (req_rx_vco_ld_val != curr_rx_vco_ld_val) |
                                (req_rx_cdr_vco_lowfreq != curr_rx_cdr_vco_lowfreq);

// Rate change request
assign req_rate_change = req_rx_vco_freq_change |
                         (req_rx_width != curr_rx_width) |
                         (req_rx_rate != curr_rx_rate);

// Hand instantiated mux on async rx_rate_i input
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_rate_mux (
  .out (req_rx_rate_nxt),
  .sel (new_req),
  .d0  (req_rx_rate),
  .d1  (rx_rate_i)
);

// Hand instantiated mux on async rx_width_i input
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_width_mux (
  .out (req_rx_width_nxt),
  .sel (new_req),
  .d0  (req_rx_width),
  .d1  (rx_width_i)
);

// Hand instantiated mux on async rx_pstate_i input
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_pstate_mux (
  .out (req_rx_pstate_nxt),
  .sel (new_req),
  .d0  (req_rx_pstate),
  .d1  (rx_pstate_i)
);

// Hand instantiated mux on async rx_lpd_i input
dwc_e12mp_phy_x4_ns_gen_mux rx_lpd_mux (
  .out (req_rx_lpd_nxt),
  .sel (new_req),
  .d0  (req_rx_lpd),
  .d1  (rx_lpd_i)
);

// Hand instantiated mux on async rx_ref_ld_val_i input
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(6)) rx_ref_ld_val_mux (
  .out (req_rx_ref_ld_val_nxt),
  .sel (new_req),
  .d0  (req_rx_ref_ld_val),
  .d1  (rx_ref_ld_val_i)
);

// Hand instantiated mux on async rx_vco_ld_val_i input
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(13)) rx_vco_ld_val_mux (
  .out (req_rx_vco_ld_val_nxt),
  .sel (new_req),
  .d0  (req_rx_vco_ld_val),
  .d1  (rx_vco_ld_val_i)
);

// Hand instantiated mux on async rx_cdr_vco_lowfreq_i input
dwc_e12mp_phy_x4_ns_gen_mux rx_cdr_vco_lowfreq_mux (
  .out (req_rx_cdr_vco_lowfreq_nxt),
  .sel (new_req),
  .d0  (req_rx_cdr_vco_lowfreq),
  .d1  (rx_cdr_vco_lowfreq_i)
);

// Hand instantiated mux on async rx_adapt_afe_en_i input
dwc_e12mp_phy_x4_ns_gen_mux rx_adapt_afe_en_mux (
  .out (req_rx_adapt_afe_en_nxt),
  .sel (new_req),
  .d0  (req_rx_adapt_afe_en),
  .d1  (rx_adapt_afe_en_i)
);

// Hand instantiated mux on async rx_adapt_dfe_en_i input
dwc_e12mp_phy_x4_ns_gen_mux rx_adapt_dfe_en_mux (
  .out (req_rx_adapt_dfe_en_nxt),
  .sel (new_req),
  .d0  (req_rx_adapt_dfe_en),
  .d1  (rx_adapt_dfe_en_i)
);

`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
// Wait counter
assign rx_wait_cnt_ne_0 = |rx_wait_cnt;
assign rx_wait_cnt_dec = rx_wait_cnt - 13'd1;
`endif

// Power state mappings
localparam PSTATE_P0  = 2'd0;
localparam PSTATE_P0S = 2'd1;
localparam PSTATE_P1  = 2'd2;
localparam PSTATE_P2  = 2'd3;

// RX ctl state machine states
localparam stRX_CTL_IDLE           = 3'd0;
localparam stRX_CTL_PMA_REQ        = 3'd1;
localparam stRX_CTL_PMA_ACK_P1     = 3'd2;
localparam stRX_CTL_PMA_REQ_RATE   = 3'd3;
localparam stRX_CTL_PMA_ACK_RATE   = 3'd4;
localparam stRX_CTL_PMA_REQ_P0_P0S = 3'd5;
localparam stRX_CTL_PMA_ACK        = 3'd6;
localparam stRX_CTL_PCS_ACK        = 3'd7;

// --------------------------------------------------
// RX ctl state machine
// --------------------------------------------------
always @ (posedge cr_clk or posedge cr_rx_rst) begin
  if (cr_rx_rst) begin
    rx_ctl_state               <= stRX_CTL_IDLE;
    rx_ctl_reset               <= 1'b1;
    req_rx_rate                <= 2'b10;
    req_rx_width               <= 2'b11;
    req_rx_pstate              <= PSTATE_P2;
    req_rx_lpd                 <= 1'b0;
    req_rx_ref_ld_val          <= 6'd20;
    req_rx_vco_ld_val          <= 13'd1000;
    req_rx_cdr_vco_lowfreq     <= 1'b1;
    req_rx_adapt_afe_en        <= 1'b0;
    req_rx_adapt_dfe_en        <= 1'b0;
    rx_ack_int                 <= 1'b1;
    rx_pma_req_int             <= 1'b0;
    rx_pma_rate_int            <= 2'b10;
    rx_pma_width_int           <= 2'b11;
    rx_pma_pstate_int          <= PSTATE_P2;
    rx_pma_lpd_int             <= 1'b0;
    rx_pma_ref_ld_val_int      <= 6'd20;
    rx_pma_vco_ld_val_int      <= 13'd1000;
    rx_pma_cdr_vco_lowfreq_int <= 1'b1;
    rx_pma_adapt_afe_en_int    <= 1'b0;
    rx_pma_adapt_dfe_en_int    <= 1'b0;
    curr_rx_rate               <= 2'b10;
    curr_rx_width              <= 2'b11;
    curr_rx_pstate             <= PSTATE_P2;
    curr_rx_lpd                <= 1'b0;
    curr_rx_ref_ld_val         <= 6'd20;
    curr_rx_vco_ld_val         <= 13'd1000;
    curr_rx_cdr_vco_lowfreq    <= 1'b1;
    curr_rx_adapt_afe_en       <= 1'b0;
    curr_rx_adapt_dfe_en       <= 1'b0;
    `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
    rx_data_en_ovrd            <= 1'b0;
    rx_data_en_ovrd_val        <= 1'b0;
    rx_valid_ovrd              <= 1'b0;
    rx_wait_cnt                <= 13'd0;
    `endif
  end else begin
    case (rx_ctl_state)
      stRX_CTL_IDLE: begin
        // RX request (or coming out of reset)
        if (new_req) begin
          req_rx_rate <= req_rx_rate_nxt;
          req_rx_width <= req_rx_width_nxt;
          req_rx_pstate <= req_rx_pstate_nxt;
          req_rx_lpd <= req_rx_lpd_nxt;
          req_rx_ref_ld_val <= req_rx_ref_ld_val_nxt;
          req_rx_vco_ld_val <= req_rx_vco_ld_val_nxt;
          req_rx_cdr_vco_lowfreq <= req_rx_cdr_vco_lowfreq_nxt;
          req_rx_adapt_afe_en <= req_rx_adapt_afe_en_nxt;
          req_rx_adapt_dfe_en <= req_rx_adapt_dfe_en_nxt;
          rx_ctl_state <= stRX_CTL_PMA_REQ;
        end
      end
         
      stRX_CTL_PMA_REQ: begin
        // if staying in P0/P0s and changing rate then move to P1, change rate then
        // move back to P0/P0s
        if (rate_chg_in_p1_r &&
            req_rate_change && (curr_rx_pstate == PSTATE_P0 || curr_rx_pstate == PSTATE_P0S)
                            && (req_rx_pstate  == PSTATE_P0 || req_rx_pstate  == PSTATE_P0S)) begin
            // only update the pstate to P1, everything else held as is
            rx_pma_req_int <= 1'b1;
            rx_pma_pstate_int <= PSTATE_P1;
            rx_ctl_state <= stRX_CTL_PMA_ACK_P1;
        end
        // else send complete request to PMA directly
        else begin
            rx_pma_req_int <= 1'b1;
            rx_pma_rate_int <= req_rx_rate;
            rx_pma_width_int <= req_rx_width;
            rx_pma_pstate_int <= req_rx_pstate;
            rx_pma_lpd_int <= req_rx_lpd;
            rx_pma_ref_ld_val_int <= req_rx_ref_ld_val;
            rx_pma_vco_ld_val_int <= req_rx_vco_ld_val;
            rx_pma_cdr_vco_lowfreq_int <= req_rx_cdr_vco_lowfreq;
            rx_pma_adapt_afe_en_int <= req_rx_adapt_afe_en;
            rx_pma_adapt_dfe_en_int <= req_rx_adapt_dfe_en;
            rx_ctl_state <= stRX_CTL_PMA_ACK;
        end
      end
      
      stRX_CTL_PMA_ACK_P1: begin
        // wait for PMA lane RX ack for P1
        if (rx_pma_ack_crclk) begin
          // deassert request to PMA lane RX
          rx_pma_req_int <= 1'b0;
          rx_ctl_state <= stRX_CTL_PMA_REQ_RATE;
        end
      end
      
      stRX_CTL_PMA_REQ_RATE: begin
        // wait for PMA lane RX ack to deassert
        if (~rx_pma_ack_crclk) begin
          // send rate change request
          rx_pma_req_int <= 1'b1;
          rx_pma_rate_int <= req_rx_rate;
          rx_pma_width_int <= req_rx_width;
          rx_pma_lpd_int <= req_rx_lpd;
          rx_pma_ref_ld_val_int <= req_rx_ref_ld_val;
          rx_pma_vco_ld_val_int <= req_rx_vco_ld_val;
          rx_pma_cdr_vco_lowfreq_int <= req_rx_cdr_vco_lowfreq;
          rx_pma_adapt_afe_en_int <= req_rx_adapt_afe_en;
          rx_pma_adapt_dfe_en_int <= req_rx_adapt_dfe_en;
          rx_ctl_state <= stRX_CTL_PMA_ACK_RATE;
        end
      end
      
      stRX_CTL_PMA_ACK_RATE: begin
        // wait for PMA lane RX ack for rate change
        if (rx_pma_ack_crclk) begin
          // deassert request to PMA lane RX
          rx_pma_req_int <= 1'b0;
          rx_ctl_state <= stRX_CTL_PMA_REQ_P0_P0S;
        end
      end
      
      stRX_CTL_PMA_REQ_P0_P0S: begin
        // wait for PMA lane RX ack to deassert
        if (~rx_pma_ack_crclk) begin
          // return to P0/P0S
          rx_pma_req_int <= 1'b1;
          rx_pma_pstate_int <= req_rx_pstate;
          rx_ctl_state <= stRX_CTL_PMA_ACK;
        end
      end
         
      stRX_CTL_PMA_ACK: begin
        // wait for PMA lane RX ack
        if (rx_pma_ack_crclk) begin
          // deassert request to PMA lane RX
          rx_pma_req_int <= 1'b0;
          rx_ctl_state <= stRX_CTL_PCS_ACK;

          `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
          // Mantis 6067
          // If RX_VCO_CAL_TOO_COARSE is defined then do the following:
          //
          // If moving from P2/P1 to P0/P0S, or rate change in P0/P0S, then
          // assert the rx_data_en, long enough to be captured by the PMA, then
          // deassert it to enable reference tracking on int_gain code.
          //
          if (~rx_fast_vco_cal_r && (// skip in fast mode
              // moving from P2/P1 to P0/P0s
              ((curr_rx_pstate == PSTATE_P1 || curr_rx_pstate == PSTATE_P2) &&
               (req_rx_pstate  == PSTATE_P0 || req_rx_pstate  == PSTATE_P0S)) ||
              // RX VCO frequency change in P0/P0s
              (req_rx_vco_freq_change &&
               (curr_rx_pstate == PSTATE_P0 || curr_rx_pstate == PSTATE_P0S) &&
               (req_rx_pstate  == PSTATE_P0 || req_rx_pstate  == PSTATE_P0S)))) begin
            // keep CDR off
            rx_data_en_ovrd <= 1'b1;
            rx_data_en_ovrd_val <= 1'b1;
            rx_valid_ovrd <= 1'b1;
            rx_wait_cnt <= {6'd0,rx_data_en_ovrd_cr_cyc[6:0]};
          end
          else begin
            rx_wait_cnt <= 13'd0;
            // assert ack to PCS
            rx_ack_int <= 1'b1;
          end
          `else
          // assert ack to PCS
          rx_ack_int <= 1'b1;
          `endif
        end
      end
         
      stRX_CTL_PCS_ACK: begin
        `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
        // wait for rx_data_en=1 to be captured in the PMA RX (rx_vco_cal)
        if (rx_wait_cnt_ne_0)
          rx_wait_cnt <= rx_wait_cnt_dec;
        else if (rx_data_en_ovrd && rx_data_en_ovrd_val) begin
          // turn off data_en to switch to reference tracking on int_gain code
          rx_data_en_ovrd_val <= 1'b0;
          rx_wait_cnt <= int_ref_trck_cr_cyc[12:0];
        end
        else if (~rx_ack_int || rx_data_en_ovrd) begin
          rx_data_en_ovrd <= 1'b0; // remove override of data_en
          // assert ack to PCS
          rx_ack_int <= 1'b1;
        end
        // wait for both PCS requests and PMA ack to deassert
        // (note: if coming out of reset, then there is no request)
        else if ((~rx_req_crclk | rx_ctl_reset) & ~rx_pma_ack_crclk) begin
        `else
        if      ((~rx_req_crclk | rx_ctl_reset) & ~rx_pma_ack_crclk) begin
        `endif
          rx_ctl_reset <= 1'b0; // release reset
          // deassert ack and return to IDLE
          rx_ack_int <= 1'b0;
          curr_rx_pstate          <= req_rx_pstate;          // update current pstate
          curr_rx_lpd             <= req_rx_lpd;             // update current lpd
          curr_rx_width           <= req_rx_width;           // update current width
          curr_rx_rate            <= req_rx_rate;            // update current rate
          curr_rx_ref_ld_val      <= req_rx_ref_ld_val;      // update current ref_ld_val
          curr_rx_vco_ld_val      <= req_rx_vco_ld_val;      // update current vco_ld_val
          curr_rx_cdr_vco_lowfreq <= req_rx_cdr_vco_lowfreq; // update current cdr_vco_lowfreq
          curr_rx_adapt_afe_en    <= req_rx_adapt_afe_en;    // update current adapt_afe_en
          curr_rx_adapt_dfe_en    <= req_rx_adapt_dfe_en;    // update current adapt_dfe_en
          `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
          // remove override on rx_valid
          // note: this is not removed earlier because it takes time for
          // previous rx_data_en_ovrd=0 to propogate through PMA
          rx_valid_ovrd <= 1'b0;
          `endif
          rx_ctl_state <= stRX_CTL_IDLE;
        end
      end
      
      default: begin
        rx_ctl_state <= stRX_CTL_IDLE;
      end
    endcase
  end
end

// -------------------------------------------------------
// Optional by-pass of entire FSM
// -------------------------------------------------------

// Hand instantiated mux on async rx_pma_ack_i input
dwc_e12mp_phy_x4_ns_gen_mux rx_ack_mux (
  .out (rx_ack_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_pma_ack_i),
  .d1  (rx_ack_int)
);

// Hand instantiated mux on async rx_pma_rate_i output
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_req_mux (
  .out (rx_pma_req_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_req_i),
  .d1  (rx_pma_req_int)
);

// Hand instantiated mux on async rx_pma_rate_i output
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_pma_rate_mux (
  .out (rx_pma_rate_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_rate_i),
  .d1  (rx_pma_rate_int)
);

// Hand instantiated mux on async rx_pma_width_i output
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_pma_width_mux (
  .out (rx_pma_width_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_width_i),
  .d1  (rx_pma_width_int)
);

// Hand instantiated mux on async rx_pma_pstate_i output
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(2)) rx_pma_pstate_mux (
  .out (rx_pma_pstate_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_pstate_i),
  .d1  (rx_pma_pstate_int)
);

// Hand instantiated mux on async rx_pma_lpd_i output
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_lpd_mux (
  .out (rx_pma_lpd_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_lpd_i),
  .d1  (rx_pma_lpd_int)
);

// Hand instantiated mux on async rx_pma_ref_ld_val_i output
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(6)) rx_pma_ref_ld_val_mux (
  .out (rx_pma_ref_ld_val_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_ref_ld_val_i),
  .d1  (rx_pma_ref_ld_val_int)
);

// Hand instantiated mux on async rx_pma_vco_ld_val_i output
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(13)) rx_pma_vco_ld_val_mux (
  .out (rx_pma_vco_ld_val_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_vco_ld_val_i),
  .d1  (rx_pma_vco_ld_val_int)
);

// Hand instantiated mux on async rx_pma_cdr_vco_lowfreq_i output
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_cdr_vco_lowfreq_mux (
  .out (rx_pma_cdr_vco_lowfreq_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_cdr_vco_lowfreq_i),
  .d1  (rx_pma_cdr_vco_lowfreq_int)
);

// Hand instantiated mux on async rx_pma_adapt_afe_en_i output
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_adapt_afe_en_mux (
  .out (rx_pma_adapt_afe_en_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_adapt_afe_en_i),
  .d1  (rx_pma_adapt_afe_en_int)
);

// Hand instantiated mux on async rx_pma_adapt_dfe_en_i output
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_adapt_dfe_en_mux (
  .out (rx_pma_adapt_dfe_en_i),
  .sel (en_rx_ctl_fsm_r),
  .d0  (rx_adapt_dfe_en_i),
  .d1  (rx_pma_adapt_dfe_en_int)
);

// -------------------------------------------------------
// Apply adapted RX values (stored in aon_lane domain)
// -------------------------------------------------------

// att
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(3)) rx_pma_eq_att_lvl_mux (
  .out (rx_pma_eq_att_lvl_i),
  .sel (rx_adapt_afe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_att_lvl_i),
  .d1  (rx_att_adpt_val_r[7:5])
);

// vga1
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(4)) rx_pma_eq_vga1_gain_mux (
  .out (rx_pma_eq_vga1_gain_i),
  .sel (rx_adapt_afe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_vga1_gain_i),
  .d1  (rx_vga_adpt_val_r[9:6])
);

// vga2
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(4)) rx_pma_eq_vga2_gain_mux (
  .out (rx_pma_eq_vga2_gain_i),
  .sel (rx_adapt_afe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_vga2_gain_i),
  .d1  (rx_vga_adpt_val_r[9:6])
);

// ctle pole
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(3)) rx_pma_eq_ctle_pole_mux (
  .out (rx_pma_eq_ctle_pole_i),
  .sel (rx_adapt_afe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_ctle_pole_i),
  .d1  (rx_ctle_pole_adpt_val_r[2:0])
);

// ctle boost
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(5)) rx_pma_eq_ctle_boost_mux (
  .out (rx_pma_eq_ctle_boost_i),
  .sel (rx_adapt_afe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_ctle_boost_i),
  .d1  (rx_ctle_boost_adpt_val_r[9:5])
);

// dfe tap1
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(8)) rx_pma_eq_dfe_tap1_mux (
  .out (rx_pma_eq_dfe_tap1_i),
  .sel (rx_adapt_dfe_en_i & rx_adpt_done_r),
  .d0  (rx_eq_dfe_tap1_i),
  .d1  (rx_dfe_tap1_adpt_val_r[12:5])
);

// dfe tap2
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(7)) rx_pma_eq_dfe_tap2_mux (
  .out (rx_pma_eq_dfe_tap2_i),
  .sel (rx_adapt_dfe_en_i & rx_adpt_done_r),
  .d0  (7'd64),
  .d1  (rx_dfe_tap2_adpt_val_r[11:5])
);

// dfe tap3
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(7)) rx_pma_eq_dfe_tap3_mux (
  .out (rx_pma_eq_dfe_tap3_i),
  .sel (rx_adapt_dfe_en_i & rx_adpt_done_r),
  .d0  (7'd64),
  .d1  (rx_dfe_tap3_adpt_val_r[11:5])
);

// dfe tap4
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(7)) rx_pma_eq_dfe_tap4_mux (
  .out (rx_pma_eq_dfe_tap4_i),
  .sel (rx_adapt_dfe_en_i & rx_adpt_done_r),
  .d0  (7'd64),
  .d1  (rx_dfe_tap4_adpt_val_r[11:5])
);

// dfe tap5
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(7)) rx_pma_eq_dfe_tap5_mux (
  .out (rx_pma_eq_dfe_tap5_i),
  .sel (rx_adapt_dfe_en_i & rx_adpt_done_r),
  .d0  (7'd64),
  .d1  (rx_dfe_tap5_adpt_val_r[11:5])
);

`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
// --------------------------------------------------------------
// Extend rx_data_en=1 to match maximum rx_data_en sampling delay in PMA
// Scale delay based on ref_range.
// --------------------------------------------------------------
always @* begin
  // only need to look at bits ref_range[1:0]
  // because cr_clk is divided by 2 for ref_range[2]=1
  case(ref_range[1:0])
    2'd0: rx_data_en_ovrd_cr_cyc = {2'b00,rx_data_en_ovrd_cnt_r[4:0]};       // x1
    2'd1: rx_data_en_ovrd_cr_cyc = { 1'b0,rx_data_en_ovrd_cnt_r[4:0],1'b0};  // x2
    2'd2: rx_data_en_ovrd_cr_cyc = { 1'b0,rx_data_en_ovrd_cnt_r[4:0],1'b0} + {2'b00,rx_data_en_ovrd_cnt_r[4:0]}; // x3
    2'd3: rx_data_en_ovrd_cr_cyc = {      rx_data_en_ovrd_cnt_r[4:0],2'b00}; // x4
  endcase
end
// --------------------------------------------------------------
// Delay PCS ack to allow the integral reference tracking 
// to pull in a max 30,000ppm coarse calibration error
// Scale delay based on ref_range.
// --------------------------------------------------------------
always @* begin
  // only need to look at bits ref_range[1:0]
  // because cr_clk is divided by 2 for ref_range[2]=1
  case(ref_range[1:0])
    2'd0: int_ref_trck_cr_cyc = {2'b00,int_ref_trck_cnt_r[10:0]};       // x1
    2'd1: int_ref_trck_cr_cyc = { 1'b0,int_ref_trck_cnt_r[10:0],1'b0};  // x2
    2'd2: int_ref_trck_cr_cyc = { 1'b0,int_ref_trck_cnt_r[10:0],1'b0} + {2'b00,int_ref_trck_cnt_r[10:0]}; // x3
    2'd3: int_ref_trck_cr_cyc = {      int_ref_trck_cnt_r[10:0],2'b00}; // x4
  endcase
end
// --------------------------------------------------
// Override rx_data_en, rx_cdr_track_en and rx_valid
// --------------------------------------------------
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_data_en_mux (
  .out (rx_pma_data_en_i),
  .sel (rx_data_en_ovrd),
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
  .d0  (rx_cdr_data_en),
`else
  .d0  (rx_data_en_i),
`endif
  .d1  (rx_data_en_ovrd_val)
);
dwc_e12mp_phy_x4_ns_gen_mux rx_pma_cdr_track_en_mux (
  .out (rx_pma_cdr_track_en_i),
  .sel (rx_data_en_ovrd),
  .d0  (rx_cdr_track_en_i),
  .d1  (1'b0)
);
`endif
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
// rx_valid has to be sync'ed to rx_clk
wire rx_clk_rst;
dwc_e12mp_phy_x4_ns_pcs_raw_gen_rst_sync rx_clk_rst_sync (
  .sync_rst        (rx_clk_rst),
  .clk             (rx_clk_i),
  .async_rst       (cr_rst | rx_reset_i),
  .scan_mode_i     (scan_mode_i),
  .scan_set_rst_i  (scan_set_rst_i)
);
`else
  `ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
// rx_valid has to be sync'ed to rx_clk
wire rx_clk_rst;
dwc_e12mp_phy_x4_ns_pcs_raw_gen_rst_sync rx_clk_rst_sync (
  .sync_rst        (rx_clk_rst),
  .clk             (rx_clk_i),
  .async_rst       (cr_rst | rx_reset_i),
  .scan_mode_i     (scan_mode_i),
  .scan_set_rst_i  (scan_set_rst_i)
);
  `endif
`endif
`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
// rx_valid_ovrd sync
wire rx_valid_ovrd_sync;
dwc_e12mp_phy_x4_ns_gen_sync sync_rx_valid_ovrd (
  .q   (rx_valid_ovrd_sync),
  .clk (rx_clk_i),
  .rst (rx_clk_rst),
  .d   (rx_valid_ovrd)
);
wire rx_valid_int;
dwc_e12mp_phy_x4_ns_gen_mux rx_valid_mux (
  .out (rx_valid_int),
  .sel (rx_valid_ovrd_sync),
  .d0  (rx_pma_valid_i),
  .d1  (1'b0)
);
always @ (posedge rx_clk_i or posedge rx_clk_rst) begin
  if (rx_clk_rst)
    rx_valid_i <= 1'b0;
  else
    rx_valid_i <= rx_valid_int;
end
`else
  `ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
assign rx_pma_data_en_i      = rx_cdr_data_en;
  `else
assign rx_pma_data_en_i      = rx_data_en_i;
  `endif
assign rx_pma_cdr_track_en_i = rx_cdr_track_en_i;
assign rx_valid_i            = rx_pma_valid_i;
`endif

// ------------------------------------------------
// Mask LOS output when LOS block is powering up
// ------------------------------------------------

// Generate an LOS signal mask when phy_rx_los_en toggles since LOS may glitch during the power-on event and 
// this glitch may be interpreted by the controller as an erroneous request to exit a low power state.

wire        los_mask_cnt_ld_rst;
wire        los_mask_cnt_ld;
wire        los_mask_cnt_ld_ext;
reg  [10:0] los_mask_cnt_cr_cyc;
reg  [10:0] los_mask_cnt;
reg         los_mask_int;
wire        los_mask;
reg         rx_reset_ack;

dwc_e12mp_phy_x4_ns_pcs_raw_gen_rst_sync #(.ATPG_COV(0)) los_mask_cnt_ld_gen_rst_sync 
(
  .sync_rst       (los_mask_cnt_ld_rst),
  .clk            (cr_clk),
  .scan_mode_i    (scan_mode_i),
  .scan_set_rst_i (scan_set_rst_i),
  .async_rst      (rx_disable_i | cr_rx_rst)
);

dwc_e12mp_phy_x4_ns_gen_sync #(.RST_VAL(1)) los_mask_cnt_ld_rst_sync (
  .q   (los_mask_cnt_ld),
  .clk (cr_clk),
  .rst (los_mask_cnt_ld_rst),
  .d   (1'b0)
);

// Extend los_mask_cnt_ld
// This also ensures that the mask counter is
// loaded before the mask is dropped
dwc_e12mp_phy_x4_ns_gen_sync #(.RST_VAL(1)) los_mask_cnt_ld_sync (
  .q   (los_mask_cnt_ld_ext),
  .clk (cr_clk),
  .rst (los_mask_cnt_ld_rst),
  .d   (los_mask_cnt_ld)
);

// ------------------------------------------------------------
// Need to apply 10us mask period
// Scale delay based on ref_range.
// ------------------------------------------------------------
always @* begin
  // Note: cr_clk is divided by 2 for ref_range[2]=1
  case(ref_range[2:0])
    3'd0: los_mask_cnt_cr_cyc = {2'b00,los_mask_cnt_r[8:0]};       // x1
    3'd1: los_mask_cnt_cr_cyc = { 1'b0,los_mask_cnt_r[8:0],1'b0};  // x2
    3'd2,
    3'd4: los_mask_cnt_cr_cyc = { 1'b0,los_mask_cnt_r[8:0],1'b0} + {2'b00,los_mask_cnt_r[8:0]}; // x3
    3'd3,
    3'd5,
    3'd6,
    3'd7: los_mask_cnt_cr_cyc = {      los_mask_cnt_r[8:0],2'b00}; // x4
  endcase
end

always @ (posedge cr_clk or posedge cr_rx_rst) begin
  if (cr_rx_rst) begin
    los_mask_cnt  <= 11'd1000;
    los_mask_int  <= 1'b1;
    rx_reset_ack  <= 1'b1;
  end else begin
    if (~rx_pma_ack_crclk)
      rx_reset_ack <= 1'b0; // when rx ack drops for the first time out of reset

    if (los_mask_cnt_ld) begin
      los_mask_cnt <= rx_fast_pwrup_r ? 11'd1 : los_mask_cnt_cr_cyc;
      los_mask_int <= 1'b1;
    end
    else begin
      los_mask_cnt <= (los_mask_cnt != 11'd0) ? (los_mask_cnt - 11'd1) : 11'd0;
      los_mask_int <= (los_mask_cnt != 11'd0) | rx_reset_ack;
    end
  end
end

assign los_mask = los_mask_int | los_mask_cnt_ld_ext;

dwc_e12mp_phy_x4_ns_gen_mux los_mux (
  .out (rx_los_i),
  .sel (los_mask),
  .d0  (rx_pma_los_i),
  .d1  (1'b1)
);

`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
// CDR lock detector module
wire [2:0]     rx_cdr_det_state;
wire [13:0]    rx_ppm_drift;
wire           rx_ppm_drift_vld;
wire           rx_ppm_drift_oflow;

dwc_e12mp_phy_x4_ns_pcs_raw_rx_ctl_cdr cdr_detector (
  // global signals
  .cr_clk                         (cr_clk),
  .cr_rx_rst                      (cr_rx_rst),
  .rx_clk                         (rx_clk_i),
  .rx_clk_rst                     (rx_clk_rst),

  // PHY Data en
  .rx_data_en_i                   (rx_data_en_i),

  // PHY config settings
  .ref_range                      (ref_range),
  .rx_pma_rate_i                  (rx_pma_rate_i),
  .rx_pma_pstate_i                (rx_pma_pstate_i),
  .rx_pma_width_i                 (rx_pma_width_i),
  .rx_pma_ref_ld_val_i            (rx_pma_ref_ld_val_i),
  .rx_pma_vco_ld_val_i            (rx_pma_vco_ld_val_i),
  .rx_pma_req_i                   (rx_pma_req_i),
  .rx_pma_valid_i                 (rx_pma_valid_i),
  .rx_cdr_ppm_max_i               (rx_cdr_ppm_max_i),

  .rx_cdr_recovery_time_r         (rx_cdr_recovery_time_r),
  .rx_cdr_detect_en_r             (rx_cdr_detector_en_r),
  .rx_cdr_ppm_monitor_mode_r      (rx_cdr_ppm_monitor_mode_r),
  .rx_cdr_detector_dis_in_adapt_r (rx_cdr_detector_dis_in_adapt_r),
  .rx_adapt_req_sync              (rx_adapt_req_sync),

  //output
  .rx_cdr_data_en                 (rx_cdr_data_en),
  .rx_ppm_drift                   (rx_ppm_drift),
  .rx_ppm_drift_vld               (rx_ppm_drift_vld),
  .rx_cdr_det_state               (rx_cdr_det_state),
  .rx_ppm_drift_oflow             (rx_ppm_drift_oflow)
);

// output ppm drift information
// only take the frist 5 bit out, should be enough for monitoring purpose
// the bit 13 is the sign bit
assign rx_ppm_drift_i     = {rx_ppm_drift[13], rx_ppm_drift_oflow ? {5{~rx_ppm_drift[13]}} : rx_ppm_drift[4:0]};
assign rx_ppm_drift_vld_i = rx_ppm_drift_vld;
`endif

// ------------------------------------------------------------------
// Generate enable for continuous offset cancellation and adaptation
// ------------------------------------------------------------------

wire rx_offcan_cont_en =   rx_offcan_cont_i
                         & lane_init_pwrup_done_r
                         & (rx_pma_pstate_i == PSTATE_P0);

wire rx_adapt_cont_en =   rx_adapt_cont_i
                        & lane_init_pwrup_done_r
                        & rx_adpt_done_r
                        & (rx_adapt_afe_en_i | rx_adapt_dfe_en_i)
                        & rx_pma_data_en_i
                        & rx_valid_i
                        & (rx_pma_pstate_i == PSTATE_P0);

// -------------------------------------------------------------------------
// %%CREG RX_FSM_CTL - RX FSM control register
//   OFFSET: 0x0
//   ATTR: READ,WRITE
//   FIELDS:
//      [1] RATE_CHG_IN_P1 - When asserted, then a rate change in P0/P0s will
//          NOTES:           be sequenced such that the RX is put in P1, the rate change is
//                           applied, and then the RX is returned to P0/P0s.
//          RESET: 0x0
//      [0] EN_RX_CTL_FSM  - Enable the RX control FSM in the Raw PCS
//          NOTES:           If enabled, then when FSM detects a rate change, it moves
//                           the RX to P1, does the rate change then goes back to P0/P0s.
//                           If not enabled, then FSM is by-passed.
//          RESET: 0x0
// ---------------------------------------------------------------------
wire [15:0] cr_rx_fsm_ctl_rd_data;
`ifdef DWC_E12MP_X4NS_RX_VCO_CAL_TOO_COARSE
dwc_e12mp_phy_x4_ns_cr_rw_reg #(.WIDTH(2), .RST_VAL(2'b01), .MSK_VAL(2'd0))
`else
dwc_e12mp_phy_x4_ns_cr_rw_reg #(.WIDTH(2), .RST_VAL(2'b00), .MSK_VAL(2'd0))
`endif
 rx_fsm_ctl_reg (
  .cr_val      ({
                 rate_chg_in_p1_r,
                 en_rx_ctl_fsm_r
                }),
  .cr_rd_data  (cr_rx_fsm_ctl_rd_data),
  .cr_wr_data  (cr_wr_data),
  .cr_wr_en    (cr_wr_en),
  .cr_clk      (cr_clk),
  .cr_rst      (cr_rst),
  .cr_sel      (cr_sel[0]),
  .cr_self_clr (1'b0)
);

// -------------------------------------------------------------------------
// %%CREG RX_LOS_MASK_CTL - RX LOS Mask Control
//   OFFSET: 0x1
//   ATTR: READ,WRITE
//   FIELDS:
//    [8:0] RX_LOS_MASK_CNT - Number of cycles (ref_range_clk) to mask out the
//          NOTES:            rx_los output, from the time the los is powered-on.
//                            Default set for minimum 10us.
//          RESET: 0x107
// ---------------------------------------------------------------------
wire [15:0] cr_rx_los_mask_ctl_rd_data;
dwc_e12mp_phy_x4_ns_cr_rw_reg #(.WIDTH(9), .RST_VAL(9'h107), .MSK_VAL(9'd0))
 rx_los_mask_ctl_reg (
  .cr_val      ({
                 los_mask_cnt_r
                }),
  .cr_rd_data  (cr_rx_los_mask_ctl_rd_data),
  .cr_wr_data  (cr_wr_data),
  .cr_wr_en    (cr_wr_en),
  .cr_clk      (cr_clk),
  .cr_rst      (cr_rst),
  .cr_sel      (cr_sel[1]),
  .cr_self_clr (1'b0)
);

// -------------------------------------------------------------------------
// %%CREG RX_DATA_EN_OVRD_CTL - RX Data Enable Override Control
//   OFFSET: 0x2
//   ATTR: READ,WRITE
//   FIELDS:
//   [15:5] INT_REF_TRCK_CNT    - Number of ref_range cycles to wait for integral
//          NOTES:                reference tracking to settle.
//          RESET: 0x3E8
//    [4:0] RX_DATA_EN_OVRD_CNT - Number of ref_range cycles to override rx_data_en to 1.
//          RESET: 0x09
// ---------------------------------------------------------------------
wire [15:0] cr_rx_data_en_ovrd_ctl_rd_data;
dwc_e12mp_phy_x4_ns_cr_rw_reg #(.WIDTH(16), .RST_VAL(16'b011_1110_1000_01001), .MSK_VAL(16'd0))
 rx_data_en_ovrd_ctl_reg (
  .cr_val      ({
                 int_ref_trck_cnt_r[10:0],
                 rx_data_en_ovrd_cnt_r[4:0]
                }),
  .cr_rd_data  (cr_rx_data_en_ovrd_ctl_rd_data),
  .cr_wr_data  (cr_wr_data),
  .cr_wr_en    (cr_wr_en),
  .cr_clk      (cr_clk),
  .cr_rst      (cr_rst),
  .cr_sel      (cr_sel[2]),
  .cr_self_clr (1'b0)
);

// %%CREG OFFCAN_CONT_STATUS - RX continuous offset cancellation status
//   OFFSET: 0x3
//   ATTR: READ, VOL, CUST
//   FIELDS:
//      [0] ENABLE     - Enable status for rx continous offset cancellation
//
wire        cr_sel_rx_offcan_cont_sts = cr_sel[3];
wire [15:0] cr_rx_offcan_cont_sts_rd_data;
dwc_e12mp_phy_x4_ns_cr_r_reg #(.WIDTH(1))
  rx_offcan_cont_sts_reg (
    .cr_val({
             rx_offcan_cont_en
             }),
    .cr_rd_data(cr_rx_offcan_cont_sts_rd_data),
    .cr_sel(cr_sel_rx_offcan_cont_sts)
);

// %%CREG ADAPT_CONT_STATUS - RX continuous adaptation status
//   OFFSET: 0x4
//   ATTR: READ, VOL, CUST
//   FIELDS:
//      [0] ENABLE     - Enable status for rx continous adaptation
//
wire        cr_sel_rx_adapt_cont_sts = cr_sel[4];
wire [15:0] cr_rx_adapt_cont_sts_rd_data;
dwc_e12mp_phy_x4_ns_cr_r_reg #(.WIDTH(1))
  rx_adapt_cont_sts_reg (
    .cr_val({
             rx_adapt_cont_en
             }),
    .cr_rd_data(cr_rx_adapt_cont_sts_rd_data),
    .cr_sel(cr_sel_rx_adapt_cont_sts)
);

`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
// %%CREG RX_PPM_DRIFT - RX CDR PPM Drift on rx clock
//   OFFSET: 0x5
//   ATTR: READ,VOL
//   FIELDS:
//       [14] RX_PPM_DRIFT_VLD  - Indicates if the PPM Drift is valid. 
//     [13:0] RX_PPM_DRIFT      - Indicates the amount of drift on rx clock when RX_PPM_DRIFT_VLD is asserted
//
wire        cr_sel_rx_ppm_drift = cr_sel[5];
wire [15:0] cr_rx_ppm_drift_rd_data;
dwc_e12mp_phy_x4_ns_cr_r_reg #(.WIDTH(15))
  rx_ppm_drift_reg (
    .cr_val({
             rx_ppm_drift_vld,
             rx_ppm_drift
             }),
    .cr_rd_data(cr_rx_ppm_drift_rd_data),
    .cr_sel(cr_sel_rx_ppm_drift)
);

// %%CREG RX_CDR_DET_STATUS - RX CDR Detector Status Register
//   OFFSET: 0x6
//   ATTR: READ,VOL
//   FIELDS:
//    [2:0] CDR_DET_STATE     - Indicate the current state for the state machine in CDR Detector 
//
wire        cr_sel_cdr_det_status = cr_sel[6];
wire [15:0] cr_cdr_det_status_rd_data;
dwc_e12mp_phy_x4_ns_cr_r_reg #(.WIDTH(3))
  cdr_det_status_reg (
    .cr_val({
             rx_cdr_det_state
             }),
    .cr_rd_data(cr_cdr_det_status_rd_data),
    .cr_sel(cr_sel_cdr_det_status)
);
`endif
   
// Muxed register read for CREG register
//     
assign cr_rd_data =   cr_rx_fsm_ctl_rd_data
                    | cr_rx_los_mask_ctl_rd_data
                    | cr_rx_data_en_ovrd_ctl_rd_data
                    | cr_rx_offcan_cont_sts_rd_data
                    | cr_rx_adapt_cont_sts_rd_data
`ifdef DWC_E12MP_X4NS_RX_CDR_PPM_DETECTOR_ADDED
                    | cr_rx_ppm_drift_rd_data
                    | cr_cdr_det_status_rd_data;
`else
                    ;
`endif
   
// ASCII decode of state for debug
// synopsys translate_off
reg [63:0] rx_ctl_state_asc;
always @ (rx_ctl_state)
begin
   case (rx_ctl_state)
     stRX_CTL_IDLE           : rx_ctl_state_asc = "IDLE    ";
     stRX_CTL_PMA_REQ        : rx_ctl_state_asc = "REQ     ";
     stRX_CTL_PMA_ACK_P1     : rx_ctl_state_asc = "ACK_P1  ";
     stRX_CTL_PMA_REQ_RATE   : rx_ctl_state_asc = "REQ_RATE";
     stRX_CTL_PMA_ACK_RATE   : rx_ctl_state_asc = "ACK_RATE";
     stRX_CTL_PMA_REQ_P0_P0S : rx_ctl_state_asc = "RQ_P0P0s";
     stRX_CTL_PMA_ACK        : rx_ctl_state_asc = "PMA_ACK ";
     stRX_CTL_PCS_ACK        : rx_ctl_state_asc = "PCS_ACK ";
     default:                  rx_ctl_state_asc = "ERR     ";
   endcase
end
// synopsys translate_on

endmodule

